package com.suoluo.zenadmin.common.file;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.springframework.web.multipart.MultipartFile;

import com.suoluo.zenadmin.common.Application;
import com.suoluo.zenadmin.common.config.SystemConfigHolder;
import com.suoluo.zenadmin.common.encrypt.EncryptUtil;

public final class UploadImageManager {

	// 新闻每10天生成一个目录
	private static long TEN_MILLIS = 10 * 24 * 60 * 60 * 1000;
	/**
	 * 行程图片的宽度
	 */
	private static int TRIP_IMG_WIDTH = 745;
	/**
	 * 行程图片的高度
	 */
	private static int TRIP_IMG_HEIGHT = 315;
	
	public static String IMAGE_PATH = "/upload/images/";
	/**
	 * 默认文件名生成器，取用当前时间的毫秒数
	 */
	private static FileNameGenerator DEFAULT_FILE_NAME_GENERATOR = new SystemMillsNameGenerator();

	private UploadImageManager() {

	}

	public static interface FileNameGenerator {
		String generate(MultipartFile mfile);
	}

	/**
	 * 保存新闻的图片
	 * 
	 * @param request
	 * @param fileKey
	 * @return
	 */
	public static FileEntry saveNewsMainImg(MultipartFile mfile) {

		// 保存在“news/子目录”的目录下
		String relativePath = "/news/" + calcNewsSubDir() + "/";
		return saveImgAndGenerateMiniImg(mfile, relativePath,
				DEFAULT_FILE_NAME_GENERATOR,
				SystemConfigHolder.getSystemImgBlockWidth(),
				SystemConfigHolder.getSystemImgBlockHeight());
	}

	/**
	 * 增加国家国旗的图片保存接口
	 * 
	 * @param request
	 * @param fileKey
	 * @return
	 */
	public static FileEntry saveCountryImg(MultipartFile mfile) {
		FileEntry entry = saveImg(mfile, "/country/",
				DEFAULT_FILE_NAME_GENERATOR);
		return entry;
	}

	/**
	 * 保存目的地的图片
	 * 
	 * @param request
	 * @param fileKey
	 * @return
	 */
	public static FileEntry saveDestImg(MultipartFile destFile, int destId) {

		// 保存在“dest/子目录”的目录下
		String relativePath = "/dest/" + destId + "/";
		return saveImgAndGenerateMiniImg(destFile, relativePath,
				DEFAULT_FILE_NAME_GENERATOR,
				SystemConfigHolder.getSystemImgBlockWidth(),
				SystemConfigHolder.getSystemImgBlockHeight());
	}

	/**
	 * 保存酒店的图片
	 * 
	 * @param request
	 * @param fileKey
	 * @return
	 */
	public static FileEntry saveHotelMainImg(MultipartFile mfile, int hotelId) {
		String preffix = "/hotel/" + hotelId + "/";
		return saveImgAndGenerateMiniImg(mfile, preffix,
				DEFAULT_FILE_NAME_GENERATOR,
				SystemConfigHolder.getSystemImgBlockWidth(),
				SystemConfigHolder.getSystemImgBlockHeight());
	}

	/**
	 * 保存酒店的附属图片，两张子图
	 * 
	 * @param request
	 * @param fileKey
	 * @param filePreffix
	 * @return
	 */
	public static FileEntry saveHotelSubImg(MultipartFile mfile,
			String filePreffix) {
		return saveImg(mfile, filePreffix, DEFAULT_FILE_NAME_GENERATOR);
	}

	/**
	 * 保存酒店的资源图片
	 * 
	 * @param request
	 *            保存请求
	 * @param mfile
	 *            资源
	 * @param hotelId
	 *            酒店编号
	 * @param serviceCategory
	 *            酒店资源类别
	 * @param resourceID
	 *            资源编号
	 * @return List<String> 保存后的资源路径
	 */
	public static List<FileEntry> saveHotelReosurceImg(MultipartFile[] files,
			int hotelId, int serviceCategory, int resourceID) {
		String relativePath = "/hotel/" + hotelId + "/" + serviceCategory + "/"
				+ resourceID + "/";
		List<FileEntry> fileEntryList = new ArrayList<FileEntry>();

		try {
			for (int i = 0; i < files.length; i++) {
				FileEntry entry = saveImg(files[i], relativePath,
						DEFAULT_FILE_NAME_GENERATOR);
				if (entry != null) {
					fileEntryList.add(entry);
				}
			}
		} catch (Exception e) {
			deleteFiles(fileEntryList);
			throw new RuntimeException(e);
		}
		return fileEntryList;
	}

	public static void deleteFiles(List<FileEntry> fileEntryList) {
		if (fileEntryList == null || fileEntryList.isEmpty()) {
			return;
		}
		for (FileEntry entry : fileEntryList) {
			deleteFile(entry);
		}
	}

	/**
	 * 压缩并且保存图片
	 * 
	 * @param request
	 * @param fileKey
	 * @param filePreffix
	 * @return
	 */
	public static FileEntry saveAutoCompressImg(MultipartFile mfile,
			String filePreffix) {
		return saveAndCompressImg(mfile, filePreffix,
				DEFAULT_FILE_NAME_GENERATOR,
				SystemConfigHolder.getSystemImgBlockWidth(),
				SystemConfigHolder.getSystemImgBlockHeight());
	}

	/**
	 * 保存目的地活动的图片
	 * 
	 * @param request
	 * @param fileKey
	 * @param destID
	 * @return
	 */
	public static FileEntry saveDestActivityImg(MultipartFile mfile, int destID) {
		String relativePath = "/dest/" + destID + "/activity/";
		return saveAutoCompressImg(mfile, relativePath);
	}

	/**
	 * 保存目的地特色的图片
	 * 
	 * @param request
	 * @param fileKey
	 * @param destID
	 * @return
	 */
	public static FileEntry saveDestFeatureImg(MultipartFile mfile, int destID) {
		String relativePath = "/dest/" + destID + "/feature/";
		return saveImgAndGenerateMiniImg(mfile, relativePath,
				DEFAULT_FILE_NAME_GENERATOR,
				SystemConfigHolder.getSystemImgBlockWidth(),
				SystemConfigHolder.getSystemImgBlockHeight());
	}

	/**
	 * 保存目的地特色项的图片
	 * 
	 * @param request
	 * @param fileKey
	 * @param destID
	 * @param featureID
	 * @return
	 */
	public static FileEntry saveDestFeatureItemImg(MultipartFile mfile,
			int destID, int featureID) {

		String relativePath = "/dest/" + destID + "/feature_item/" + featureID
				+ "/";
		return saveImgAndGenerateMiniImg(mfile, relativePath,
				DEFAULT_FILE_NAME_GENERATOR,
				SystemConfigHolder.getSystemImgBlockWidth(),
				SystemConfigHolder.getSystemImgBlockHeight());
	}

	/**
	 * 保存大图 图片
	 * 
	 * @param request
	 * @param fileKey
	 * @param imageType
	 * @return
	 */
	public static FileEntry saveBigImg(MultipartFile mfile, int imageType) {
		// 获取大图的保存路径
		String relativePath = "/big/" + imageType + "/";
		return saveImg(mfile, relativePath, DEFAULT_FILE_NAME_GENERATOR);
	}

	/**
	 * 保存酒店服务图标
	 * 
	 * @param request
	 *            请求
	 * @param fileKey
	 *            文件关联的属性name
	 * @return String 返回保存后的路径
	 */
	public static FileEntry saveHotelServiceCategoryIcon(MultipartFile mfile) {
		String relativePath = "/hotel/service_category/";
		return saveImg(mfile, relativePath, DEFAULT_FILE_NAME_GENERATOR);
	}

	/**
	 * 替换图片和图片的小图片
	 * 
	 * @param request
	 * @param oldEntry
	 * @param fileKey
	 * @return
	 */
	public static FileEntry replaceImgAndMiniImg(MultipartFile mfile,
			FileEntry oldEntry) {
		FileEntry entry = saveImgAndGenerateMiniImg(mfile,
				oldEntry.getFilePreffix(), DEFAULT_FILE_NAME_GENERATOR,
				SystemConfigHolder.getSystemImgBlockWidth(),
				SystemConfigHolder.getSystemImgBlockHeight());
		// 没有替换文件，则不需要删除
		if (entry != null) {
			//删除图片
			deleteFile(oldEntry);
		}
		return entry;
	}

	public static FileEntry replaceFile(MultipartFile mfile, FileEntry oldEntry) {
		FileEntry entry = saveImg(mfile, oldEntry.getFilePreffix(),
				DEFAULT_FILE_NAME_GENERATOR);
		// 没有替换文件，则不需要删除
		if (entry != null) {
			deleteFile(oldEntry);
		}
		return entry;
	}

	

	public static FileEntry replaceAutoCompressFile(MultipartFile mfile,
			FileEntry oldEntry) {
		FileEntry entry = saveAutoCompressImg(mfile, oldEntry.getFilePreffix());
		// 没有替换文件，则不需要删除
		if (entry != null) {
			deleteFile(oldEntry);
		}
		return entry;
	}

	private static String calcNewsSubDir() {
		// 当前毫秒数
		long mills = System.currentTimeMillis();
		return String.valueOf(mills / TEN_MILLIS);
	}

	/**
	 * 删除图片和图片的小图片
	 * 
	 * @param entry
	 */
	public static void deleteFile(FileEntry entry) {
		if (entry != null) {
			// 删除原始图片
			deleteFile(entry.getFilePath());
			// 删除原始图片的小图片
			deleteFile(entry.getMiniFilePath());
		}
	}

	/**
	 * 删除文件
	 * 
	 * @param request
	 * @param filePath
	 */
	public static void deleteFile(String filePath) {
		
		Application a = Application.getInstance();
		StringBuilder imgPath = new StringBuilder(a.getPath("/"));
		String path = imgPath.append(IMAGE_PATH).append(filePath).toString();
		
		File file = new File(path);
		if (file.exists() && file.isFile()) {
			if (!file.delete()) {
				throw new RuntimeException("fail to delete img,filePath = "
						+ path);
			}
		} else {
			// 如果文件不存在则直接返回
			return;
		}

		// 如果父目录是空的需要删除该目录
		File parentDir = file.getParentFile();
		if (parentDir.listFiles() != null) {
			while (parentDir.listFiles().length == 0) {
				parentDir.delete();
				parentDir = parentDir.getParentFile();
			}
		}
	}

	private static FileEntry saveImg(MultipartFile mfile, String relativePath,
			FileNameGenerator generator) {
		if (mfile == null || mfile.getSize() == 0) {
			return null;
		}

		String relativeDir = SystemConfigHolder.getRelativeUploadImageRoot()
				+ relativePath;
		Application a = Application.getInstance();
		String abstractDirPath = a.getPath("/") + relativeDir;

		// 验证当前路径是否存在
		File saveDir = new File(abstractDirPath);
		if (!saveDir.exists()) {
			if (!saveDir.mkdirs()) {
				throw new RuntimeException("fail to mkdirs,path="
						+ abstractDirPath);
			}
		}
		if (generator == null) {
			generator = DEFAULT_FILE_NAME_GENERATOR;
		}
		// 生成文件名称
		String fileName = generator.generate(mfile);

		// 保存图片
		String filePath = abstractDirPath + fileName;
		// 保存图片
		FileUtils.saveFile(filePath, mfile);
		FileEntry entry = new FileEntry(relativePath, fileName);
		return entry;
	}

	private static FileEntry saveAndCompressImg(MultipartFile mfile,
			String relativePath, FileNameGenerator generator,
			int compressWidth, int compressHeight) {
		if (mfile == null || mfile.getSize() == 0) {
			return null;
		}

		StringBuilder imgPath = new StringBuilder(IMAGE_PATH);
		imgPath.append(relativePath);
		Application a = Application.getInstance();
		String abstractDirPath = a.getPath("/") + imgPath;
		// 验证当前路径是否存在
		File saveDir = new File(abstractDirPath);
		if (!saveDir.exists()) {
			if (!saveDir.mkdirs()) {
				throw new RuntimeException("fail to mkdirs,path="
						+ abstractDirPath);
			}
		}
		if (generator == null) {
			generator = DEFAULT_FILE_NAME_GENERATOR;
		}
		// 生成文件名称
		String fileName = generator.generate(mfile);
		// 保存图片
		String filePath = abstractDirPath + fileName;
		try {
			ImageUtils.compressImage(mfile.getInputStream(),
					new File(filePath), compressHeight, compressWidth);
			return new FileEntry(relativePath, fileName);
		} catch (IOException e) {
			throw new RuntimeException("fail to save and compress img", e);
		}
	}

	/**
	 * 保存大图，并且生成小图
	 * 
	 * @param request
	 * @param fileKey
	 * @param relativePath
	 * @param generator
	 * @return
	 */
	private static FileEntry saveImgAndGenerateMiniImg(MultipartFile mfile,
			String relativePath, FileNameGenerator generator, int miniImgWidth,
			int miniImgHeight) {

		if (mfile == null || mfile.getSize() == 0) {
			return null;
		}
		StringBuilder imgPath = new StringBuilder(IMAGE_PATH);
		imgPath.append(relativePath);
		Application a = Application.getInstance();
		String abstractDirPath = a.getPath("/") + imgPath;
		// 验证当前路径是否存在
		File saveDir = new File(abstractDirPath);
		if (!saveDir.exists()) {
			if (!saveDir.mkdirs()) {
				throw new RuntimeException("fail to mkdirs,path="
						+ abstractDirPath);
			}
		}
		if (generator == null) {
			generator = DEFAULT_FILE_NAME_GENERATOR;
		}
		// 生成文件名称
		String fileName = generator.generate(mfile);

		// 保存图片
		String filePath = abstractDirPath + fileName;
		
		File origiFile = new File(filePath);
		// 保存大图，声称小图
		try {
			FileUtils.writeFile(origiFile, mfile.getInputStream());
			// 迷你小图的路径
			String miniFilePath = abstractDirPath
					+ SystemConfigHolder.getMiniImgPreffix() + fileName;
			File outputMiniFile = new File(miniFilePath);
			ImageUtils.compressImage(origiFile, outputMiniFile, miniImgHeight,
					miniImgWidth);
			// relativePath必须要有“/”
			FileEntry entry = new FileEntry(relativePath, fileName);
			return entry;
		} catch (IOException e) {
			if (origiFile.exists()) {
				origiFile.delete();
			}
			throw new RuntimeException(
					"fail to compress img,(mfile.getInputStream())", e);
		}
	}

	private static class SystemMillsNameGenerator implements FileNameGenerator {

		private static String[] chars = new String[] { // 要使用生成URL的字符
		"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
				"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
				"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B",
				"C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
				"O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
		private final Random rand = new Random();

		@Override
		public String generate(MultipartFile mfile) {
			String suffix = FileUtils.parseFileNameSuffix(mfile
					.getOriginalFilename());
			String fileName = shortText(mfile.getOriginalFilename()) + suffix;
			return fileName;
		}

		public String shortText(String string) {
			// String key = "XuLiang"; //自定义生成MD5加密字符串前的混合KEY

			String hex = EncryptUtil.md5(System.currentTimeMillis() + string);
			// int hexLen = hex.length();
			// int subHexLen = hexLen / 8;
			// String[] ShortStr = new String[4];
			int offset = rand.nextInt(4);
			// for (int i = 0; i < subHexLen; i++) {
			StringBuilder text = new StringBuilder(6);
			int j = offset + 1;
			String subHex = hex.substring(offset * 8, j * 8);
			long idx = Long.valueOf("3FFFFFFF", 16) & Long.valueOf(subHex, 16);

			for (int k = 0; k < 6; k++) {
				int index = (int) (Long.valueOf("0000003D", 16) & idx);
				text.append(chars[index]);
				idx = idx >> 5;
			}
			return text.toString();
		}
	}

	/**
	 * 保存风格偏好首页特色类别图片
	 * 
	 * @param request
	 * @param fileKey
	 * @return
	 */
	public static FileEntry saveHomeStyleItemImg(MultipartFile mfile) {
		FileEntry entry = saveImg(mfile, "/style/", DEFAULT_FILE_NAME_GENERATOR);
		return entry;
	}

	public static void main(String[] args) {
		// ImageUtils.compressImage("D:/c/美食745-315.jpg", "D:/c/美食235-180.jpg",
		// 180, 235);
		String md5 = EncryptUtil
				.md5(System.currentTimeMillis()
						+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbfffffffffffffffewqfrewfewaspfisapufopdsaufodsaufowuew0quo0quofjojfdsajfsdpafjdsa");
		System.out.println(md5.length());
		System.out.println(md5.substring(3 * 8, 4 * 8));
	}

	/**
	 * 保存友情链接类别项图片
	 * 
	 * @param request
	 * @param fileKey
	 * @return
	 */
	public static FileEntry saveFriendItemImg(MultipartFile mfile) {
		FileEntry entry = saveImg(mfile, "/friend/",
				DEFAULT_FILE_NAME_GENERATOR);
		return entry;
	}
	/**
	 * 保存特色类别图标
	 * 
	 * @param request
	 * @param fileKey
	 * @param imageType
	 * @return
	 */
	public static FileEntry saveFeatureCategoryImg(MultipartFile mfile) {
		// 获取大图的保存路径
		String relativePath = "/category/";
		return saveImg(mfile, relativePath, DEFAULT_FILE_NAME_GENERATOR);
	}
	
	public static FileEntry saveTripImg(MultipartFile mfile)
	{
		// 获取大图的保存路径
		String relativePath = "/trip/";
		FileEntry entry = saveImgAndGenerateMiniImg(mfile, relativePath,
				DEFAULT_FILE_NAME_GENERATOR,
				SystemConfigHolder.getSystemImgBlockWidth(),
				SystemConfigHolder.getSystemImgBlockHeight());
		
		Application a = Application.getInstance();
		StringBuilder imgPath = new StringBuilder(a.getPath("/"));
		imgPath.append(IMAGE_PATH).append(entry.getFilePath());
		String filePath = imgPath.toString();
		
		ImageUtils.compressImage(filePath,filePath,TRIP_IMG_HEIGHT,TRIP_IMG_WIDTH);
		
		return entry;
	}
}
